# -*- coding: utf-8 -*-
#
# Author:: Jonny
# Date:: 2020/7/22
import os
import uuid

from functools import reduce

from submodules.common.lib.local_paths import project_tmp_images_path
from submodules.common.lib.datetime_ import get_timestamp_ms
from submodules.common.lib.log_ import logger



from PIL import Image


def image_diff():
    pass


def _phash(img):
    img = img.resize((20, 20), Image.ANTIALIAS).convert('L')

    avg = reduce(lambda x, y: x + y, img.getdata()) / 400.
    return reduce(
        lambda x, y: x | (y[1] << y[0]),
        enumerate(map(lambda i: 0 if i < avg else 1, img.getdata())),
        0
    )


def _hamming_distance(a, b):
    return bin(a ^ b).count('1')


def img_cut(image_path_in, bounds_tuple, image_path_out_suffix="", image_path_out=None):
    '''

    :param filename_in: "img/current.png"
    :param filename_out: "img/current_cut.png"
    :param _tuple: (396, 1601, 666, 1668)
    :return:
    '''
    # for i in range(30):
    #     if os.path.exists(image_path_in):
    #         break
    #     else:
    #         pass
    #     sleep(0.1)

    if image_path_out == None:
        image_path_out = os.path.join(project_tmp_images_path,
                                      get_timestamp_ms() + "-" + image_path_out_suffix + "-" + str(
                                          uuid.uuid1()) + ".png")

    img = Image.open(image_path_in)
    cropped = img.crop(bounds_tuple)  # (left, upper, right, lower)
    cropped.save(image_path_out)
    return image_path_out


def get_current_shot(suffix="", file_path=None):
    if file_path == None:
        file_path = os.path.join(project_tmp_images_path, suffix + "-" + str(uuid.uuid1()) + ".png")
    r = os.popen("adb exec-out screencap -p > %s" % file_path)
    r.close()
    # os.system("adb shell screencap -p /sdcard/%s" % file_name)
    # os.system("adb pull /sdcard/%s %s" % (file_name, file_dir))
    return file_path


def is_images_similar_by_hanming(image_path1, image_path2, threshold=5):
    img1 = Image.open(image_path1)
    img2 = Image.open(image_path2)
    hamming_distance = _hamming_distance(_phash(img1), _phash(img2))
    return True if hamming_distance <= threshold else False


def get_image_hanming_distance(image_path1, image_path2):
    img1 = Image.open(image_path1)
    img2 = Image.open(image_path2)
    hamming_distance = _hamming_distance(_phash(img1), _phash(img2))
    return hamming_distance


def is_images_similar_by_opencv():
    pass


def is_images_similar_by_deep_learning():
    pass


def is_images_similar(image_path1, image_path2, mode="hanming"):
    if mode == "hanming":
        is_images_similar_by_hanming(image_path1, image_path2)
    elif mode == "opencv":
        is_images_similar_by_opencv(image_path1, image_path2)
    elif mode == "deep_learning":
        is_images_similar_by_deep_learning()


def __get_bin_table(threshold=115):
    '''
    获取灰度转二值的映射table
    0表示黑色,1表示白色
    '''
    table = []
    for i in range(256):
        if i < threshold:
            table.append(0)
        else:
            table.append(1)
    return table


def reduce_noise(img_obj, threshold):
    '''
    降噪
    :param img_path_in:
    :param img_path_out:
    :param threshold:
    :return:
    '''
    # 对于问道验证码 threshold=130最佳
    imgry = img_obj.convert('L')
    table = __get_bin_table(threshold)
    binary = imgry.point(table, '1')
    return binary


def reduce_noise_file(img_path_in, img_path_out=None, threshold=130):
    '''
    降噪
    :param img_path_in:
    :param img_path_out:
    :param threshold:
    :return:
    '''
    # 对于问道验证码 threshold=130最佳
    if img_path_out is None:
        img_path_out = os.path.join(project_tmp_images_path, get_timestamp_ms() + "-" + str(uuid.uuid1()) + ".png")

    image = Image.open(img_path_in)
    binary = reduce_noise(image, threshold)
    binary.save(img_path_out)
    logger.info(f"img_path_out:{img_path_out}")
    return img_path_out


if __name__ == "__main__":
    # get_current_shot("img/current.png")
    # (422, 1593), (722, 1663)
    # // [396, 1601][666, 1668]
    # (422, 1593, 663, 1671)

    def img_cut_test():
        img_cut("test_data/test.png", (0, 0, 100, 100))
